<template>
  <div v-loading.body.fullscreen.lock="loading" :element-loading-text="loadingText" ref="containerRef"
    class="container"></div>

  <DescDialog ref="descDialogRef" :currentRow="currentRow"></DescDialog>
  <VideoDialog ref="videoDialogRef" :currentRow="currentRow" />
</template>
<script setup>
import * as THREE from "three";
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";
import {
  CSS2DRenderer,
  CSS2DObject,
} from "three/addons/renderers/CSS2DRenderer.js";
import DescDialog from "./common/descDialog/index.vue";
import VideoDialog from "./common/videoControlDialog/index.vue";
import gsap from "gsap";
import { GUI } from "dat.gui";
import modelDatas from "@/assets/json/model.json";
import 出现紧急情况1 from "@/assets/imgs/map/出现紧急情况 (1).png";
import {
  generateFluctuatingAltitude,
  generateRandomLicensePlate,
} from "@/utils/index.js";
import { nextTick } from "vue";

console.log("modelDatas", modelDatas);

let scene,
  camera,
  renderer,
  controls,
  clock,
  ambientLight,
  directionalLight,
  globalTime,
  css2Renderer,
  followTarget,
  draco,
  loader,
  masterModel;
let timer = null;
const descDialogRef = useTemplateRef("descDialogRef");
const videoDialogRef = useTemplateRef("videoDialogRef");
const labelElements = []; // 存储所有标签DOM元素用于遮挡判断
const carMap = new Map();
const mixers = []; // 全局存储所有动画混合器
const cameraOffset = new THREE.Vector3(10, 5, 0);
const lerpAlpha = 0.06; // 阻尼系数，范围 0–1
const containerRef = useTemplateRef("containerRef");
const loading = ref(false);
const loadingText = ref("加载中...");
const isDark = useDark();
const route = useRoute();
const currentRow = ref({});
const hasMoved = ref(false); // 是否移动过摄像头
const modelData = modelDatas.model.find((i) => i.name == route.query?.name);
const isMobile = inject("isMobile");

let cardDatas = [];

switch (route.query?.name) {
  case "金沙江":
    cardDatas = [
      {
        number: generateRandomLicensePlate(),
        type: "大巴车",
        speed: 60,
        altitude: generateFluctuatingAltitude(2400, 100),
      },
      {
        number: generateRandomLicensePlate(),
        type: "大巴车",
        speed: 60,
        altitude: generateFluctuatingAltitude(2400, 100),
      },
      /* {
          name: '大巴01',
          url: '/车辆动画/大巴01.gltf',
          img: 大巴车
      }, */
      {
        number: generateRandomLicensePlate(),
        type: "大巴车",
        speed: 67,
        altitude: generateFluctuatingAltitude(2400, 100),
      },
      // {
      //     name: '大巴02.002',
      //     position: '/车辆动画/大巴02.002.gltf',
      // },
      /*   {
            name: '大巴02',
            url: '/车辆动画/大巴02.gltf',
            img: 大巴车
        }, */
      {
        number: generateRandomLicensePlate(),
        type: "货车",
        speed: 66,
        altitude: generateFluctuatingAltitude(2400, 100),
      },
      {
        number: generateRandomLicensePlate(),
        type: "货车",
        speed: 70,
        altitude: generateFluctuatingAltitude(2400, 100),
      },
      /*   {
            name: '货车01',
            url: '/车辆动画/货车01.gltf',
            img: 货车
        }, */
      {
        number: generateRandomLicensePlate(),
        type: "货车",
        speed: 58,
        altitude: generateFluctuatingAltitude(2400, 100),
      },
      {
        number: generateRandomLicensePlate(),
        type: "货车",
        speed: 50,
        altitude: generateFluctuatingAltitude(2400, 100),
      },
      /* {
          name: '货车02',
          url: '/车辆动画/货车02.gltf',
          img: 货车
      }, */
      // {
      //     name: '桥车01.001',
      //     url: '/车辆动画/桥车01.001.gltf',
      // },
      // {
      //     name: '桥车01.002反向',
      //     url: '/车辆动画/桥车01.002反向.gltf',
      // },
      // {
      //     name: '桥车01',
      //     url: '/车辆动画/桥车01.gltf',
      // },
      {
        number: generateRandomLicensePlate(),
        type: "汽车",
        speed: 60,
        altitude: generateFluctuatingAltitude(2400, 100),
      },
      {
        number: generateRandomLicensePlate(),
        type: "汽车",
        speed: 66,
        altitude: generateFluctuatingAltitude(2400, 100),
      },
      /*  {
           name: '皮卡01',
           url: '/车辆动画/皮卡01.gltf',
           img: 汽车
       }, */
    ];
    break;
  case "然乌镇":
    cardDatas = [
      {
        number: generateRandomLicensePlate(),
        type: "大巴车",
        speed: 55,
        altitude: generateFluctuatingAltitude(3900, 100),
      },
      {
        number: generateRandomLicensePlate(),
        type: "货车",
        speed: 60,
        altitude: generateFluctuatingAltitude(3900, 100),
      },
      {
        number: generateRandomLicensePlate(),
        type: "货车",
        speed: 67,
        altitude: generateFluctuatingAltitude(3900, 100),
      },
      {
        number: generateRandomLicensePlate(),
        type: "轿车",
        speed: 64,
        altitude: generateFluctuatingAltitude(3900, 100),
      },
      {
        number: generateRandomLicensePlate(),
        type: "皮卡",
        speed: 62,
        altitude: generateFluctuatingAltitude(3900, 100),
      },
    ];
    break;
  case "二郎山":
    cardDatas = [
      {
        number: generateRandomLicensePlate(),
        type: "大巴车",
        speed: 55,
        altitude: generateFluctuatingAltitude(2100, 100),
      },
      {
        number: generateRandomLicensePlate(),
        type: "大巴车",
        speed: 67,
        altitude: generateFluctuatingAltitude(2100, 100),
      },
      {
        number: generateRandomLicensePlate(),
        type: "货车",
        speed: 62,
        altitude: generateFluctuatingAltitude(2100, 100),
      },
      {
        number: generateRandomLicensePlate(),
        type: "货车",
        speed: 60,
        altitude: generateFluctuatingAltitude(2100, 100),
      },
      {
        number: generateRandomLicensePlate(),
        type: "轿车",
        speed: 58,
        altitude: generateFluctuatingAltitude(2100, 100),
      },
      {
        number: generateRandomLicensePlate(),
        type: "皮卡",
        speed: 62,
        altitude: generateFluctuatingAltitude(2100, 100),
      },
    ];
    break;
  case "龙泉山":
    cardDatas = [
      {
        number: generateRandomLicensePlate(),
        type: "大巴车",
        speed: 50,
        altitude: generateFluctuatingAltitude(2110, 100),
      },
      {
        number: generateRandomLicensePlate(),
        type: "大巴车",
        speed: 42,
        altitude: generateFluctuatingAltitude(2120, 100),
      },
      {
        number: generateRandomLicensePlate(),
        type: "大巴车",
        speed: 64,
        altitude: generateFluctuatingAltitude(2109, 100),
      },
      {
        number: generateRandomLicensePlate(),
        type: "大巴车",
        speed: 68,
        altitude: generateFluctuatingAltitude(2100, 100),
      },
      {
        number: generateRandomLicensePlate(),
        type: "大巴车",
        speed: 67,
        altitude: generateFluctuatingAltitude(2200, 100),
      },
      {
        number: generateRandomLicensePlate(),
        type: "大巴车",
        speed: 65,
        altitude: generateFluctuatingAltitude(2000, 100),
      },
    ];
    break;
  default:
    cardDatas = [
      {
        number: generateRandomLicensePlate(),
        type: "大巴车",
        speed: 50,
        altitude: generateFluctuatingAltitude(2110, 100),
      },
      {
        number: generateRandomLicensePlate(),
        type: "大巴车",
        speed: 42,
        altitude: generateFluctuatingAltitude(2120, 100),
      },
      {
        number: generateRandomLicensePlate(),
        type: "大巴车",
        speed: 64,
        altitude: generateFluctuatingAltitude(2109, 100),
      },
      {
        number: generateRandomLicensePlate(),
        type: "大巴车",
        speed: 68,
        altitude: generateFluctuatingAltitude(2100, 100),
      },
      {
        number: generateRandomLicensePlate(),
        type: "大巴车",
        speed: 67,
        altitude: generateFluctuatingAltitude(2200, 100),
      },
      {
        number: generateRandomLicensePlate(),
        type: "大巴车",
        speed: 65,
        altitude: generateFluctuatingAltitude(2000, 100),
      },
      {
        number: generateRandomLicensePlate(),
        type: "大巴车",
        speed: 61,
        altitude: generateFluctuatingAltitude(2200, 100),
      },
      {
        number: generateRandomLicensePlate(),
        type: "大巴车",
        speed: 64,
        altitude: generateFluctuatingAltitude(2400, 100),
      },
      {
        number: generateRandomLicensePlate(),
        type: "大巴车",
        speed: 67,
        altitude: generateFluctuatingAltitude(2100, 100),
      },
      {
        number: generateRandomLicensePlate(),
        type: "大巴车",
        speed: 68,
        altitude: generateFluctuatingAltitude(2000, 100),
      },
      {
        number: generateRandomLicensePlate(),
        type: "大巴车",
        speed: 60,
        altitude: generateFluctuatingAltitude(2000, 100),
      },
    ];
    break;
}

/** 监听点击视角自定义事件 */
const watchAngle = () => {
  window.addEventListener("changeAngle", (e) => {
    console.log("www", e.detail);
    const { angle, back } = e.detail;
    if (timer) clearTimeout(timer);
    hasMoved.value = false;
    moveCamera(angle, masterModel.position);
    clearAllLabel();
  });
};

/** 监听危险监测表格的点击事件 */
const watchDangerTableClick = () => {
  window.addEventListener("clickWateHanle", (e) => {
    console.log("row", e.detail);
    const { row } = e.detail;
    if (["rockfall", "freeze", "water"].includes(row.type)) {
      const dom = document.querySelector("#" + row.type);
      dom.querySelector(".img").style.display = "block";
      setTimeout(() => {
        dom.querySelector(".img").style.display = "none";
      }, 10000);
    } else {
      currentRow.value = modelData.disasterPoints.find(
        (i) => i.name == row.name
      );
      const dom = document.querySelector("#" + row.type);
      console.log("dom", dom);
      const text = dom.querySelector(".text");
      text.style.opacity = 1;
      nextTick(() => {
        descDialogRef.value?.open(text);
      });
    }
  });
};

/** 加载汽车 */
const loadCards = () => {
  // cardDatas
  if (!masterModel) return;
  modelData.cardDatas.forEach((i, index) => {
    console.log("车辆动画", i);
    loader.load(i.url, (gltf) => {
      const model = gltf.scene;
      // createHelper(model.children[0].position)
      console.log("车辆动画model", model);
      const dom = document.createElement("div");
      dom.className = "card";
      dom.innerHTML = `
                <img class="img" src="${i.icon}" alt="">
            `;
      const tag = new CSS2DObject(dom);
      tag.position.set(0, isMobile.value ? 8 : 8, 0);
      tag.name = "label";
      model.children[0].add(tag);
      scene.add(model);

      labelElements.push({ dom: dom, object3D: tag });

      // 创建动画混合器
      const mixer = new THREE.AnimationMixer(model);
      mixer.speed = 0.1;
      mixers.push(mixer);
      // 播放动画
      const action = mixer.clipAction(gltf.animations[0]);
      action.timeScale = 0.5; // 2倍速播放
      action.play();

      i.data = cardDatas[index];
      const dom2 = document.createElement("div");
      dom2.className = "cardPopup";
      dom2.innerHTML = `
           <div class="header">
      <div class="title">车辆信息</div>
        <img src="/prefix/close.png" class="close" alt="">
           </div>
            <div class="content1">
              <div class="item">
                <span>车牌号：</span>
                <span>${i.data.number}</span>
             </div> 
              <div class="item">
                <span>车辆类型：</span>
                <span>${i.data.type}</span>
             </div>
              <div class="item">
                <span>行驶速度：</span>
                <span class="speed">${i.data.speed}km/h</span> 
             </div>
              <div class="item">
                <span>海拔高度：</span>
                <span>${i.data.altitude}M</span>
             </div>
            </div>
            `;
      const tags1 = new CSS2DObject(dom2);
      tags1.position.set(0, 5, 0);
      tags1.name = "popup";
      tags1.visible = false;
      model.children[0].add(tags1);

      // 添加点击事件
      dom.addEventListener("click", (e) => {
        e.stopPropagation();
        clearAllLabel();
        timedCloseCardPopup();

        carMap.set(model, {
          initialSpeed: Number(i.data.speed) || 60, // 强制转换为数值
          speedElement: dom2.querySelector(".speed"),
          mixer: mixer,
          currentFactor: 1, // 当前速度因子
          targetFactor: 3, // 目标速度因子
          acceleration: 0.003,
          isMaxSpeed: false,
        });

        window.dispatchEvent(
          new CustomEvent("footerClick", { detail: { type: "other" } })
        );

        model.children[0].children.find(
          (i) => i.name == "popup"
        ).visible = true;
        model.children[0].children.find(
          (i) => i.name == "label"
        ).visible = false;
        followTarget = model.children[0];

        const worldPos = new THREE.Vector3();
        const worldQuat = new THREE.Quaternion();
        followTarget.getWorldPosition(worldPos);
        followTarget.getWorldQuaternion(worldQuat);
        controls.target.lerp(worldPos, lerpAlpha);
        moveCamera(masterModel.position, followTarget.position);
      });

      // 关闭按钮
      dom2.querySelector(".close").addEventListener("click", (e) => {
        e.stopPropagation();
        window.dispatchEvent(
          new CustomEvent("footerClick", { detail: { type: "back" } })
        );
        clearAllLabel();
        move();
      });
    });
  });
};

/** 清除汽车弹窗 */
const clearCardLabel = () => {
  scene.traverse((child) => {
    if (child.name == "popup") child.visible = false;
    if (child.name == "label") child.visible = true;
  });
}; /** 清除汽车动画并移动到初始视角 */
const clearCardLoop = () => {
  followTarget = null;
  if (timer) clearTimeout(timer);
};
/** 15sw后自动关闭弹窗 */
const timedCloseCardPopup = () => {
  timer = setTimeout(() => {
    move();
    window.dispatchEvent(
      new CustomEvent("footerClick", { detail: { type: "back" } })
    );
  }, 15000);
};

/** 加载灾害点 */
const loadDisasterPoints = () => {
  if (!masterModel) return;
  modelData.disasterPoints.forEach((i) => {
    const dom = document.createElement("div");
    dom.className = "disasterPoints";
    dom.id = i.class;
    dom.innerHTML = `
       <div class="text">${i.name}</div>
       <img class="img" src="${i.icon}" alt="">
     `;
    const img = dom.querySelector(".img");
    const text = dom.querySelector(".text");
    const tag = new CSS2DObject(dom);
    tag.position.set(i.position.x, i.position.y, i.position.z);
    labelElements.push({ dom: dom, object3D: tag });
    // masterModel.add(tag)
    scene.add(tag); // 添加到场景而非obj

    img.addEventListener("click", (e) => {
      currentRow.value = i;
      e.stopPropagation();
      clearAllLabel();
      text.style.opacity = 1;
      descDialogRef.value.open(text); // 打开弹窗
    });
  });
};

/** 加载描述点 */
const loadDescPoints = () => {
  if (!masterModel) return;
  const children = masterModel.children;
  modelData.descPoints.forEach((i) => {
    const obj = children.find((j) => j.name == i.name);
    console.log(i.name, obj);

    if (!obj) return;
    const dom = document.createElement("div");
    dom.className = "introduce";
    dom.innerHTML = `
      <div class="text">${i.title}</div>
      <img class="img" src="${i.icon}" alt="">
    `;
    const img = dom.querySelector(".img");
    const text = dom.querySelector(".text");
    const tag = new CSS2DObject(dom);
    const worldPos = new THREE.Vector3();
    obj.updateMatrixWorld();
    obj.getWorldPosition(worldPos);
    worldPos.y += 0; // 补偿高度差（根据实际图标尺寸调整）
    tag.position.copy(worldPos);
    labelElements.push({ dom: dom, object3D: tag });
    // scene.add(tag) // 添加到场景而非obj
    // obj.add(tag); // 添加到obj
    scene.add(tag);

    img.addEventListener("click", (e) => {
      currentRow.value = i;
      e.stopPropagation();
      move();
      // text.style.opacity = 1;
      // descDialogRef.value.open(text); // 打开弹窗
      descDialogRef.value.open(); // 打开弹窗
    });
  });
};
/** 加载道路点 */
const loadRoadPoints = () => {
  if (!masterModel) return;
  modelData.roadPoints.forEach((i) => {
    const obj = masterModel.children.find((child) => child.name == i.name);
    if (!obj) return;
    // 复制模型坐标
    const modelWorldPos = new THREE.Vector3();
    obj.getWorldPosition(modelWorldPos);
    loader.load(i.url, (gltf) => {
      const model = gltf.scene;
      model.position.set(modelWorldPos.x, modelWorldPos.y, modelWorldPos.z);
      model.rotation.set(
        i.rotation[0] * (Math.PI / 180),
        i.rotation[1] * (Math.PI / 180),
        i.rotation[2] * (Math.PI / 180)
      );
      model.name = i.name;
      scene.add(model);
    });

    const dom = document.createElement("div");
    dom.id = i.class;
    dom.className = "road";
    dom.innerHTML = `
                    <img class="img" src="${出现紧急情况1}" alt="">
                    <span class="text">${i.title}</span>
                `;
    const tag = new CSS2DObject(dom);
    // tag.position.z += 4 // 标签高度偏移量
    labelElements.push({ dom: dom, object3D: tag });
    obj.add(tag); // 标签跟随父对象移动
  });
};

/** 加载摄像头点 */
const loadMonitoringPoints = () => {
  if (!masterModel) return;
  modelData.monitoringPoints.forEach((i) => {
    const obj = masterModel.children.find((child) => child.name === i.name);
    if (!obj) return;
    const dom = document.createElement("div");
    dom.className = "monitoring";
    dom.style.pointerEvents = "auto"; // 确保点击事件能触发
    dom.innerHTML = `
     <div class="text textDom">点击查看</div>
    <img class="img" src="${i.icon}" alt="">
    `;
    const tag = new CSS2DObject(dom);
    labelElements.push({ dom: dom, object3D: tag });
    obj.add(tag);

    const img = dom.querySelector(".img");
    const text = dom.querySelector(".text");
    img.addEventListener("click", (e) => {
      e.stopPropagation();
      clearAllLabel();
      text.style.opacity = 1;
      window.dispatchEvent(
        new CustomEvent("footerClick", { detail: { type: "other" } })
      );

      const modelWorldPos = new THREE.Vector3();
      obj.getWorldPosition(modelWorldPos);
      const cameraOffset = new THREE.Vector3(10, 0, 5);
      const cameraTargetPos = modelWorldPos.clone().add(cameraOffset);
      if (currentRow.value?.name !== i.name) {
        currentRow.value = i;
        hasMoved.value = false;
        moveCamera(cameraTargetPos, modelWorldPos);
        hasMoved.value = true;
      } else {
        if (hasMoved.value) {
          videoDialogRef.value.open(text);
          hasMoved.value = false; // 重置状态
        } else {
          moveCamera(cameraTargetPos, modelWorldPos);
          hasMoved.value = true;
        }
      }
    });
  });
};
/** 清除摄像头标签 */
const clearMonitoringLabel = () => {
  const textDoms = document.querySelectorAll(".textDom");
  textDoms?.forEach((item) => {
    item.style.opacity = 0;
  });
};
/** 清除所有的标签 */
const clearAllLabel = () => {
  clearCardLabel();
  clearCardLoop();
  clearMonitoringLabel();
};

const loadModel = () => {
  loading.value = true;
  const { url, angles } = modelData;
  loader.load(url, (gltf) => {
    loading.value = false;
    const model = gltf.scene;
    masterModel = model;
    scene.add(masterModel);
    camera.position.set(
      angles[0].position.x,
      angles[0].position.y,
      angles[0].position.z
    );
    console.log("加载完成", model);
    loadDisasterPoints();
    loadDescPoints();
    loadRoadPoints();
    loadMonitoringPoints();
    loadCards();
  });
};

/** 移动相机 */
const moveCamera = (targetPos, lookAtPos, onComplete) => {
  if (!lookAtPos) return;
  const tl = gsap.timeline({ defaults: { duration: 2, ease: "power2.inOut" } });
  // 位置动画
  tl.to(
    camera.position,
    {
      x: targetPos.x,
      y: targetPos.y,
      z: targetPos.z,
    },
    "start"
  );

  // 目标点动画（同步执行）
  tl.to(
    controls.target,
    {
      x: lookAtPos.x,
      y: lookAtPos.y,
      z: lookAtPos.z,
      onUpdate: () => controls.update(),
    },
    "start"
  );

  // 状态管理
  tl.call(() => {
    controls.enabled = true;
    onComplete?.();
  });
};

watch(
  () => isDark.value,
  () => {
    if (scene) {
      initLight();
    }
  }
);
const initLight = () => {
  const { dark, light } = modelData.threeSetting.light;
  console.log("a", dark, light);

  if (ambientLight) scene.remove(ambientLight);
  if (directionalLight) scene.remove(directionalLight);
  if (isDark.value) {
    // 暗黑模式
    // scene.background = new THREE.Color(0x000000);
    // if (ambientLight) scene.remove(ambientLight);
    // if (directionalLight) scene.remove(directionalLight);

    scene.background = new THREE.Color(parseInt(dark.color, 16)); // 黑色
    scene.fog = new THREE.Fog(
      parseInt(dark.fog.color, 16),
      dark.fog.near,
      dark.fog.far
    ); // 雾Near设为50，避免近处物体完全被雾覆盖
    directionalLight = new THREE.DirectionalLight(
      parseInt(dark.directional.color, 16),
      dark.directional.intensity
    );
    scene.add(directionalLight);
  } else {
    // 正常模式
    scene.background = new THREE.Color(parseInt(light.color, 16)); // 天空蓝色
    ambientLight = new THREE.AmbientLight(
      parseInt(light.ambient.color, 16),
      light.ambient.intensity
    );
    scene.add(ambientLight);
    directionalLight = new THREE.DirectionalLight(
      parseInt(light.directional.color, 16),
      light.directional.intensity
    );
    directionalLight.position.set(
      light.directional.position[0],
      light.directional.position[2],
      light.directional.position[3]
    ); // 提高光源高度以生成自然投影
    directionalLight.castShadow = true; // 启用阴影投射
    directionalLight.shadow.camera.top = light.directional.top;
    directionalLight.shadow.camera.bottom = light.directional.bottom;
    directionalLight.shadow.camera.left = light.directional.left;
    directionalLight.shadow.camera.right = light.directional.right;
    scene.add(directionalLight);
    scene.fog = null;
  }
  if (renderer) {
    renderer.shadowMap.enabled = true; // 启用阴影贴图
    renderer.shadowMap.type = THREE.PCFSoftShadowMap; // 使用软阴影优化边缘质量
  }
};
const initThree = () => {
  const { controls: controls1, camera: camera1 } = modelData.threeSetting;
  renderer = new THREE.WebGLRenderer({ antialias: true });
  renderer.setSize(window.innerWidth, window.innerHeight);
  renderer.domElement.style.zIndex = -1;
  containerRef.value.appendChild(renderer.domElement);

  scene = new THREE.Scene();
  camera = new THREE.PerspectiveCamera(
    75,
    window.innerWidth / window.innerHeight,
    0.1,
    camera1.heigth
  );
  controls = new OrbitControls(camera, renderer.domElement);

  // controls.enableDamping = true;
  // controls.dampingFactor = 0.25;
  controls.enablePan = controls1.enablePan; // 启用平移
  // 控制器限制
  controls.minDistance = controls1.minDistance; // 最小距离
  controls.maxDistance = controls1.maxDistance; // 最大距离

  controls.minPolarAngle = controls1.minPolarAngle; // 0 = 正上方
  controls.maxPolarAngle = controls1.maxPolarAngle * (Math.PI / 180); // π/2 = 水平视角

  camera.position.set(0, 0, 0);
  controls.target.set(0, 0, 0);
  controls.update();

  initLight();
  // // 添加天空颜色
  // scene.background = new THREE.Color(0x87CEEB); // 天空蓝色

  // // 添加环境光
  // ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
  // scene.add(ambientLight);

  // // 添加平行光
  // directionalLight = new THREE.DirectionalLight(0xffffff, 1);
  // directionalLight.position.set(5, 5, 5);
  // scene.add(directionalLight);

  // 创建时钟
  clock = new THREE.Clock();

  // 创建gsap时间线
  globalTime = gsap.timeline({ paused: true });
};
/** 创建css2渲染器 */
const initCSS2Renderer = () => {
  css2Renderer = new CSS2DRenderer();
  css2Renderer.setSize(window.innerWidth, window.innerHeight);
  css2Renderer.domElement.style.position = "absolute";
  css2Renderer.domElement.style.top = "0px";
  css2Renderer.domElement.style.pointerEvents = "none";
  css2Renderer.domElement.classList.add("css2");
  containerRef.value.appendChild(css2Renderer.domElement);
  css2Renderer.domElement.style.zIndex = 0;
};
/** 初始化draco */
const initDraco = () => {
  draco = new DRACOLoader();
  draco.setDecoderPath("/prefix/draco/");
};
/** 初始话loader */
const initLoader = () => {
  loader = new GLTFLoader();
  loader.setDRACOLoader(draco);
};
/** 检测标签是否被模型遮挡 */
const checkOcclusion = () => {
  const raycaster = new THREE.Raycaster();
  const cameraPosition = camera.position.clone();

  labelElements.forEach(({ dom, object3D }) => {
    // 1. 获取标签的世界坐标（不修改原始值）
    const labelWorldPos = new THREE.Vector3();
    object3D.getWorldPosition(labelWorldPos);

    // 2. 计算射线方向（从相机到标签）
    const rayDirection = labelWorldPos.clone().sub(cameraPosition).normalize();

    // 3. 设置射线（起点稍微靠近相机，避免近裁剪面问题）
    const rayOrigin = cameraPosition
      .clone()
      .add(rayDirection.multiplyScalar(0.1));
    raycaster.set(rayOrigin, rayDirection);

    // 4. 检测遮挡（排除标签自身和透明物体）
    const intersects = raycaster.intersectObjects(scene.children, true);
    const isOccluded = intersects.some((intersect) => {
      return (
        intersect.distance < cameraPosition.distanceTo(labelWorldPos) - 0.1 && // 容差阈值
        !intersect.object.isLabel &&
        !(intersect.object.material && intersect.object.material.transparent)
      );
    });

    // 5. 更新标签可见性
    dom.style.visibility = isOccluded ? "hidden" : "visible";
  });
};
let requestAnimationFrameId;
/** 添加动画循环 */
const animate = () => {
  requestAnimationFrameId = requestAnimationFrame(animate);
  // 更新所有动画混合器
  const delta = clock.getDelta();
  mixers.forEach((mixer) => {
    mixer.getRoot().updateMatrixWorld(true); // 关键：强制更新根节点矩阵
    mixer.update(delta);
  });

  if (followTarget) {
    // 1. 世界空间的位置与旋转
    const worldPos = new THREE.Vector3();
    const worldQuat = new THREE.Quaternion();
    followTarget.getWorldPosition(worldPos);
    followTarget.getWorldQuaternion(worldQuat);
    // 2. 偏移向量按模型朝向旋转
    const localOffset = cameraOffset.clone().applyQuaternion(worldQuat);
    // 3. 目标相机位置
    const desiredPos = worldPos.clone().add(localOffset);
    // 4. 平滑过渡
    // camera.position.lerp(desiredPos, lerpAlpha);
    controls.target.lerp(worldPos, lerpAlpha);
  }
  carMap.forEach((data, model) => {
    if (!data.speedElement || data.isMaxSpeed) return;
    data.currentFactor += data.acceleration * delta;
    if (data.currentFactor >= data.targetFactor) {
      data.currentFactor = data.targetFactor;
      data.isMaxSpeed = true;
    }
    const currentSpeed = data.initialSpeed * data.currentFactor;
    data.speedElement.textContent = `${currentSpeed.toFixed(1)}km/h`;
    if (data.mixer) {
      data.mixer.speed = data.currentFactor * 0.1;
    }
  });

  checkOcclusion();

  // 确保场景矩阵更新
  scene.updateMatrixWorld(true);

  renderer.render(scene, camera);
  controls.update();
  css2Renderer.render(scene, camera);
};
// 添加窗口resize处理
const onWindowResize = () => {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
  css2Renderer.setSize(window.innerWidth, window.innerHeight);
};
onMounted(() => {
  initThree();
  initCSS2Renderer();
  initDraco();
  initLoader();
  loadModel();
  animate();
  watchAngle();
  watchDangerTableClick();
  window.addEventListener("resize", onWindowResize);
});
onUnmounted(() => {
  window.removeEventListener("resize", onWindowResize);
  if (renderer) renderer.dispose();
  if (timer) clearTimeout(timer);
  if (requestAnimationFrameId) cancelAnimationFrame(requestAnimationFrameId);
});

/** 移动相机恢复初始位子 */
const move = () => {
  const { url, angles } = modelData;
  if (timer) clearTimeout(timer);
  hasMoved.value = false;
  // currentRow.value = {};
  moveCamera(
    {
      x: angles[0].position.x,
      y: angles[0].position.y,
      z: angles[0].position.z,
    },
    masterModel.position
  );
  clearAllLabel();
};

/** 创建辅助线 */
const createHelper = (
  position = {
    x: 0,
    y: 0,
    z: 0,
  }
) => {
  const axesHelper = new THREE.AxesHelper(50)
  axesHelper.position.set(position.x, position.y, position.z) // 设置辅助线的位置
  scene.add(axesHelper)
}
defineExpose({ move });
</script>
<style scoped lang="scss">
.container {
  width: 100%;
  height: 100%;
}
</style>
